package com.woniu113.junk.site.service.impl;

import cn.hutool.json.JSONUtil;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu113.junk.commons.model.Result;
import com.woniu113.junk.site.client.OrderClient;
import com.woniu113.junk.site.client.UserClient;
import com.woniu113.junk.site.client.dto.AdminInfo;
import com.woniu113.junk.site.client.dto.OrderInfo;
import com.woniu113.junk.site.dto.*;
import com.woniu113.junk.site.exception.InventoryException;
import com.woniu113.junk.site.mapper.InboundLogMapper;
import com.woniu113.junk.site.mapper.StationInfoMapper;
import com.woniu113.junk.site.mapper.WasteTransferStatisticsMapper;
import com.woniu113.junk.site.model.InboundLog;
import com.woniu113.junk.site.model.Inventory;
import com.woniu113.junk.site.mapper.InventoryMapper;
import com.woniu113.junk.site.model.StationInfo;
import com.woniu113.junk.site.model.WasteTransferStatistics;
import com.woniu113.junk.site.param.inventory.WareHouseParam;
import com.woniu113.junk.site.service.InventoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu113.junk.site.service.StationInfoService;
import com.woniu113.junk.site.util.Data;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 蜡笔没了小新
 * @since 2024年10月16日
 */
@Service
public class InventoryServiceImpl extends ServiceImpl<InventoryMapper, Inventory> implements InventoryService {
    @Resource
    private OrderClient orderClient;
    @Resource
    private InventoryMapper inventoryMapper;
    @Resource
    private UserClient userClient;
    @Resource
    private InboundLogMapper inboundLogMapper;
    @Resource
    private WasteTransferStatisticsMapper wasteTransferStatisticsMapper;
    @Resource
    private StationInfoService stationInfoService;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private StationInfoMapper stationInfoMapper;
    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void wareHouse(WareHouseParam param,Integer adminId) {
        //1.判断数据完整性
        if (param==null){
            throw new InventoryException("没有可以入库的订单数据",8001);
        }
        //3.获取当前登录管理员的信息
        String adminName = userClient.selectAdminById(adminId).getData().getAdminName();
        //4.判断订单是否存在
        OrderInfo orderInfo = orderClient.findById(param.getOrderNum()).getData();
        if (orderInfo==null){
            throw new InventoryException("没有可以入库的订单数据",8001);
        }
        //2.得到订单所属的站点id
        Integer stationId1 = orderInfo.getStationId();

        ArrayList<OrderInfoDTO.WasteInfo> wasteInfos = new ArrayList<>();

        for (WareHouseParam.WasteInfo wasteInfo : param.getWasteList()) {
            //获取骑手对应类型重量
            Double weight1 = orderClient.queryWeight(param.getOrderNum(), wasteInfo.getTypeId()).getData();
            if (weight1==null){
                throw new InventoryException("与骑手订单废品类型不符",8015);
            }
            //获取前端传入对应类型的重量
            Double weight2 = wasteInfo.getWeight();
            System.out.println("种1"+weight1);
            System.out.println("种2"+weight2);
            //计算重量差
            Double difference = weight1-weight2;
            if (difference<0){
                throw new InventoryException("入库重量不能比骑手订单重量大",8015);
            }
            if (difference> weight1*0.03){
                if (param.getIsError().equals("否")){
                    throw new InventoryException("经后台检测订单异常,请重新入库",8016);
                }
            }
            OrderInfoDTO.WasteInfo wasteInfo1 = new OrderInfoDTO.WasteInfo();
            wasteInfo1.setTypeId(wasteInfo.getTypeId());
            wasteInfo1.setWeight(wasteInfo.getWeight());
            wasteInfo1.setActualLossWeight(difference);
            wasteInfos.add(wasteInfo1);
        }
        //5.获取前端传入订单编号中的废品详情数据
        List<WareHouseParam.WasteInfo> wasteList = param.getWasteList();
        for (WareHouseParam.WasteInfo wasteInfo : wasteList) {
            Integer typeId = wasteInfo.getTypeId();
            //6.判断库存表中是否存在要入库的废品类型
            Inventory inventory = inventoryMapper.selectById(typeId);
            if (inventory==null){//为空,表示库存表中没有要新增库存中的类型,此时需要向数据库中插入一条库存数据
                Inventory inventory1 = new Inventory();
                inventory1.setTypeId(typeId);
                inventory1.setNumber(wasteInfo.getWeight());
                inventory1.setStationId(orderInfo.getStationId());
                inventoryMapper.insert(inventory1);
                System.out.println("已************");
            }else {//库存表中存在要新增库存中的类型,此时需要修改该条数据中的库存量即可
                inventory.setNumber(inventory.getNumber()+ wasteInfo.getWeight());
                inventoryMapper.updateById(inventory);
            }
        }
        //7.填入日志
        ArrayList<OrderInfoDTO> orderInfoDTOS = new ArrayList<>();
        OrderInfoDTO orderInfoDTO = new OrderInfoDTO();
        orderInfoDTO.setOrderNum(param.getOrderNum());
        if (param.getIsError().equals("是")){//是异常的,填入异常原因(实际损耗均有)
            orderInfoDTO.setLossReason(param.getLossReason());
            //记录该订单骑手的该订单状态为异常
            orderClient.abnormalAdd(param.getOrderNum());
        }else {
            //记录该订单骑手的该订单状态为正常
            orderClient.normalAdd(param.getOrderNum());
        }
        orderInfoDTO.setWasteList(wasteInfos);
        orderInfoDTOS.add(orderInfoDTO);

        InboundLog inboundLog = new InboundLog();
        inboundLog.setOrderInfo(JSONUtil.parse(orderInfoDTOS).toString());
        inboundLog.setAdminId(adminId);
        inboundLog.setAdminName(adminName);
        inboundLog.setStationId(stationId1);
        inboundLog.setInboundTime(LocalDateTime.now());
        inboundLog.setDescription(Data.LOG_ORDER);
        inboundLogMapper.insert(inboundLog);
    }

    @Override
    public void fWareHouse(Integer transferId, Integer adminId) throws JsonProcessingException {
        //1.判断数据完整性
        if (transferId==null ||adminId==null){
            throw new InventoryException("请将数据填写完整",8004);
        }
        //2.查询当前登录管理员是否存在
        Result<AdminInfo> adminInfo = userClient.selectAdminById(adminId);
        if (adminInfo==null){
            throw new InventoryException("该管理员不存在",8005);
        }
        //2.判断是否存在转移数据
        QueryWrapper<WasteTransferStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transfer_id",transferId).eq("state",Data.TRANSFER_ING);
        WasteTransferStatistics wasteTransferStatistics = wasteTransferStatisticsMapper.selectOne(queryWrapper);
        if (wasteTransferStatistics==null){
            throw new InventoryException("不存在该转移数据",8006);
        }
        //3.获取转移的废品详情
        List<TransferWasteInfoDTO.WasteInfo> wasteInfoList = JSONUtil.toList(wasteTransferStatistics.getWasteInfo(), TransferWasteInfoDTO.WasteInfo.class);
        for (TransferWasteInfoDTO.WasteInfo wasteInfo : wasteInfoList) {
            //4.存入库存表(根据typeId找到库存信息)
            Inventory inventory = inventoryMapper.selectById(wasteInfo.getTypeId());
            if (inventory==null){//库存表中不存在该废品类型的数据,新建一条
                Inventory inventory1 = new Inventory();
                inventory1.setTypeId(wasteInfo.getTypeId());
                inventory1.setNumber(wasteInfo.getWeight());
                inventory1.setStationId(wasteTransferStatistics.getCountyStationId());//区站点(目标站点)
                inventoryMapper.insert(inventory1);
            }else {
                //库存表中存在该废品类型的数据,修改该条数据的number字段
                if (inventory.getNumber()==0 ||inventory.getNumber()==null){//库存量为0或null
                    inventory.setNumber(wasteInfo.getWeight());
                }else {
                    inventory.setNumber(inventory.getNumber()+wasteInfo.getWeight());
                }
            }
        }
        //5.修改转移表中的数据(结束时间/状态)
        wasteTransferStatistics.setEndTime(LocalDateTime.now());
        wasteTransferStatistics.setState(Data.TRANSFER_END);
        wasteTransferStatisticsMapper.updateById(wasteTransferStatistics);
        //6.存入日志信息
        InboundLog inboundLog = new InboundLog();
        inboundLog.setOrderInfo(JSONUtil.parse(wasteInfoList).toString());
        inboundLog.setAdminId(adminId);
        inboundLog.setAdminName(adminInfo.getData().getAdminName());
        inboundLog.setStationId(wasteTransferStatistics.getCountyStationId());////区站点(目标站点)
        inboundLog.setInboundTime(LocalDateTime.now());
        inboundLog.setDescription(Data.LOG_TRANSFER);
        inboundLogMapper.insert(inboundLog);
    }

    @Override
    public List<InventoryDTO> findInventoryByStationId(Integer stationId) {
        //1.判断数据完整性
        if (stationId==null){
            throw new InventoryException("请将数据填写完整",8004);
        }
        //2.判断是否存在该站点
        StationInfo stationInfo = stationInfoService.getById(stationId);
        if (stationInfo.getStationState()!=Data.STATION_STATE_OPEN){
            throw new InventoryException("该站点不存在",8003);
        }
        //3.查询站点库存信息
        List<InventoryDTO> inventoryDTOS = inventoryMapper.findInventoryByStationId(stationId);
        return inventoryDTOS;
    }

    @Override
    public List<ChildInventoryDTO> findAllChildInventoryByCountyStationId(Integer stationId) {
        //1.判断数据完整性
        if (stationId==null){
            throw new InventoryException("请将数据填写完整",8004);
        }
        //2.判断是否存在该站点
        StationInfo stationInfo = stationInfoService.getById(stationId);
        if (stationInfo.getStationState()!=Data.STATION_STATE_OPEN){
            throw new InventoryException("该区站点不存在",8003);
        }
        //3.查询当前区站点是否存在子站点
        List<StationInfo> childStations = stationInfoService.findChildStationById(stationId);
        if (childStations.isEmpty()){
            throw new InventoryException("该区站点不存在子站点",8007);
        }
        //4存在子站点,进行循环
        ArrayList<ChildInventoryDTO> childInventoryDTOS = new ArrayList<>();
        for (StationInfo childStation : childStations) {
            ChildInventoryDTO childInventoryDTO = new ChildInventoryDTO();
            childInventoryDTO.setStationId(childStation.getStationId());
            childInventoryDTO.setStationName(childStation.getStationName());
            //定义废品库存集合来存储该子站点的所有废品库存信息
            ArrayList<ChildInventoryDTO.WasteInfo> wasteInfos = new ArrayList<>();
            //根据子站点id查询该子站点的所有库存信息
            List<InventoryDTO> inventoryDTOS = inventoryService.findInventoryByStationId(childStation.getStationId());
            //判断是否存在子站点库存信息
            if (inventoryDTOS.isEmpty()){
                throw new InventoryException("该子站点不存在库存信息",8008);
            }
            //将废品信息存入废品库存集合中
            for (InventoryDTO inventoryDTO : inventoryDTOS) {
                ChildInventoryDTO.WasteInfo wasteInfo = new ChildInventoryDTO.WasteInfo();
                wasteInfo.setTypeId(inventoryDTO.getTypeId());
                wasteInfo.setTypeName(inventoryDTO.getTypeName());
                wasteInfo.setNumber(inventoryDTO.getNumber());
                wasteInfos.add(wasteInfo);
            }
            //将wasteInfos存入
            childInventoryDTO.setWasteList(wasteInfos);
            //存入大集合中
            childInventoryDTOS.add(childInventoryDTO);
        }
        return childInventoryDTOS;
    }

    @Override
    public AllInventoryDTO findAll(String stationName, Integer pageNum, Integer pageSize) {
        int offset = (pageNum - 1) * pageSize; // 计算 offset
        List<InventoryDTO> inventoryDTOS = inventoryMapper.findAll(stationName,pageSize,offset);

        int total = inventoryMapper.countAll(stationName);
        System.out.println("总条数"+total);
        AllInventoryDTO allInventoryDTO = new AllInventoryDTO();
        allInventoryDTO.setList(inventoryDTOS);
        allInventoryDTO.setTotal(total);
        return allInventoryDTO;
    }
}
